<?php

include_once(_CORE_PATH. 'router/router_protocol_prototype.php');
class router_http extends router_protocol_prototype
{
	const SKIPENCODEURL = "SKIPENCODE\0";
	
	private $_moduleRouter;
	private $_ctrlRouter = array();
	
	private function GetCtrlRouter($moduleName)
	{
		if (!$this->_ctrlRouter[$moduleName]) 
		{
			$filePath = _APP_PATH. 'modules/' .$moduleName. '/router/router_' .$moduleName. '_http.php';
			
			if (!is_file($filePath)) return false;
			
			include_once($filePath);
			
			$className = 'router_' .$moduleName. '_http';
			$this->_ctrlRouter[$moduleName] = new $className();
		}
		return $this->_ctrlRouter[$moduleName];
	}
	
	private function GetModuleRouter()
	{
		if (!$this->_moduleRouter) 
		{
			include_once(_APP_PATH. 'router/router_http_module.php');
			$this->_moduleRouter = new RouterHttpModule();
		}
		return $this->_moduleRouter;
	}	
	
	public function Create($elements = array(), $buildParams = true, &$params = array())
	{
		$elements = (array)$elements;
		$urlParts = array_reverse($this->Build($elements));
		
		$nUrlParts = array();
		$c = 0;
		foreach ($urlParts as $part)
		{
			$part = trim(str_replace(router_http::SKIPENCODEURL, '', $part, $c), '/');
			if (!$c) $part = urlencode($part);
			if (strlen($part)) $nUrlParts[] = $part;
			else if (sizeof($nUrlParts)) $nUrlParts[] = 'default';
		}
		
		if ($buildParams) $paramsStr = http_build_query($elements);
		else 
		{
			$paramsStr = false;
			$params = $elements;
		}
		
		return _ROOT_URL.implode('/', array_reverse($nUrlParts)).(strlen($paramsStr) ? '?' .$paramsStr : '');		
	}
	
	public function CreateInputs($elements = array())
	{
		$inputs = '';
		
		$elements = (array)$elements;
		foreach ($elements as $name => $value)
		{
			$inputs .= '<input type="hidden" name="' .htmlspecialchars($name). '" value="' .htmlspecialchars($value). '">';
		}
		
		return $inputs;
	}
	
	public function Route()
	{
		$request = SysLoader::GetRequest('http');
		$requestUri = $request->getRequestUri();
		
        list ($requestUri) = explode('?', $requestUri);       
        
        $segments = explode('/', trim($requestUri, '/'));		
		$segments = array_map('urldecode', $segments);
        
		$elements = $this->Parse($segments);

		$moduleName = $this->GetModuleRouter()->DetectModule($elements);
		/**
		 * если остались элементы в segments, значит путь полностью не обработан => ошибка
		 */
		if (sizeof($segments))
		{
			return array($moduleName, false, false);
		}
		
		if ($ctrlRouter = $this->GetCtrlRouter($moduleName))		
		{
			list($ctrlName, $actionName) = $ctrlRouter->DetectCtrlAndAction($elements);
		}

		$_GET = array_merge($_GET, $elements);
		
		return array($moduleName, $ctrlName, $actionName);
	}
	
	public function Build(array &$elements = array())
	{
		$urlParts = array();
		
		$moduleName = $this->GetModuleRouter()->DetectModule($elements);
		$urlParts = array_merge($urlParts, (array)$this->GetModuleRouter()->Build($elements));
		
		if ($ctrlRouter = $this->GetCtrlRouter($moduleName))
		{
			list($ctrlName) = $ctrlRouter->DetectCtrlAndAction($elements);
			$urlParts = array_merge($urlParts, (array)$ctrlRouter->Build($elements));
			
			if ($ctrlName)
			{
				$buildMethod = 'Build' .$ctrlName;
				if (method_exists($ctrlRouter, $buildMethod))
				{
					$urlParts = array_merge($urlParts, (array)$ctrlRouter->$buildMethod($elements));
				}
			}
		}
		
		return $urlParts;
	}
	
	public function Parse(array &$segments = array())
	{	
		$elements = array();
		$elements = array_merge($elements, (array)$this->GetModuleRouter()->Parse($segments));
		$moduleName = $this->GetModuleRouter()->DetectModule($elements);
		if ($ctrlRouter = $this->GetCtrlRouter($moduleName))
		{
			$elements = array_merge($elements, $ctrlRouter->Parse($segments));
			list($ctrlName) = $ctrlRouter->DetectCtrlAndAction($elements);
			if ($ctrlName)
			{
				$parseMethod = 'Parse' .$ctrlName;
				if (method_exists($ctrlRouter, $parseMethod))
				{
					$elements = array_merge($elements, (array)$ctrlRouter->$parseMethod($segments));
				}
			}			
		}
		
		return $elements;
	}
	
	public function Redirect($elements = array())
	{
		SysLoader::GetResponse('http')->setRedirect($this->Create($elements))->sendHeaders();
		exit;
	}
}